<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Heart Particle Effect</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js"></script>
  <script>
    // Scene, Camera, Renderer
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // Particle Geometry
    const heartShape = new THREE.Shape();
    heartShape.moveTo(0, 0);
    heartShape.bezierCurveTo(2.5, 2.5, 5, 0, 0, -5);
    heartShape.bezierCurveTo(-5, 0, -2.5, 2.5, 0, 0);

    const points = heartShape.getPoints(50);
    const particleGeometry = new THREE.BufferGeometry().setFromPoints(points);

    const particleCount = 2000;
    const positions = new Float32Array(particleCount * 3);

    for (let i = 0; i < particleCount; i++) {
      const i3 = i * 3;
      const randomPoint = points[Math.floor(Math.random() * points.length)];
      positions[i3] = randomPoint.x + (Math.random() - 0.5) * 2;
      positions[i3 + 1] = randomPoint.y + (Math.random() - 0.5) * 2;
      positions[i3 + 2] = (Math.random() - 0.5) * 2;
    }

    particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));

    // Particle Material
    const particleMaterial = new THREE.PointsMaterial({
      color: 0xff0000,
      size: 0.05,
    });

    // Particle System
    const particleSystem = new THREE.Points(particleGeometry, particleMaterial);
    scene.add(particleSystem);

    // Camera positioning
    camera.position.z = 10;

    // Animation
    function animate() {
      requestAnimationFrame(animate);

      particleSystem.rotation.y += 0.01;
      particleSystem.rotation.x += 0.01;

      renderer.render(scene, camera);
    }

    animate();

    // Handle window resize
    window.addEventListener('resize', () => {
      renderer.setSize(window.innerWidth, window.innerHeight);
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
    });
  </script>
</body>
</html>
